From 14d11ebcab4f704610f151859a86da62f51db927 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 2 Jun 2020 12:42:53 -0400 Subject: [PATCH] listbase: Use a widget for the rubberband We no longer need to juggle manual css nodes. Just create a widget for the rubberband, and update its allocation as we rubberband. --- gtk/gtkgridview.c | 2 + gtk/gtklistbase.c | 113 +++++++++++++-------------------------- gtk/gtklistbaseprivate.h | 2 + gtk/gtklistview.c | 2 + 4 files changed, 44 insertions(+), 75 deletions(-) diff --git a/gtk/gtkgridview.c b/gtk/gtkgridview.c index debfcf0946..7590446858 100644 --- a/gtk/gtkgridview.c +++ b/gtk/gtkgridview.c @@ -713,6 +713,8 @@ gtk_grid_view_size_allocate (GtkWidget *widget, int x, y; guint i; + gtk_list_base_allocate_rubberband (GTK_LIST_BASE (widget)); + orientation = gtk_list_base_get_orientation (GTK_LIST_BASE (self)); scroll_policy = gtk_list_base_get_scroll_policy (GTK_LIST_BASE (self), orientation); opposite_orientation = OPPOSITE_ORIENTATION (orientation); diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index cf0e4e2912..cae6f0d736 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -30,10 +30,10 @@ #include "gtktypebuiltins.h" #include "gtkgesturedrag.h" #include "gtkwidgetprivate.h" -#include "gtkcssnodeprivate.h" #include "gtkstylecontextprivate.h" #include "gtksnapshot.h" #include "gtkmultiselection.h" +#include "gtkgizmoprivate.h" typedef struct _GtkListBasePrivate GtkListBasePrivate; @@ -58,13 +58,12 @@ struct _GtkListBasePrivate GtkListItemTracker *focus; gboolean enable_rubberband; - gboolean doing_rubberband; double rb_x1; double rb_y1; double rb_x2; double rb_y2; GtkGesture *drag_gesture; - GtkCssNode *rubberband_node; + GtkWidget *rubberband; GtkSelectionModel *old_selection; gboolean modify; gboolean extend; @@ -1083,20 +1082,6 @@ gtk_list_base_add_custom_move_binding (GtkWidgetClass *widget_class, "(bbb)", TRUE, TRUE, TRUE); } -static void gtk_list_base_snapshot_rubberband (GtkListBase *self, - GtkSnapshot *snapshot); - -static void -gtk_list_base_snapshot (GtkWidget *widget, - GtkSnapshot *snapshot) -{ - GtkListBase *self = GTK_LIST_BASE (widget); - - GTK_WIDGET_CLASS (gtk_list_base_parent_class)->snapshot (widget, snapshot); - - gtk_list_base_snapshot_rubberband (self, snapshot); -} - static void gtk_list_base_class_init (GtkListBaseClass *klass) { @@ -1105,7 +1090,6 @@ gtk_list_base_class_init (GtkListBaseClass *klass) gpointer iface; widget_class->focus = gtk_list_base_focus; - widget_class->snapshot = gtk_list_base_snapshot; gobject_class->dispose = gtk_list_base_dispose; gobject_class->get_property = gtk_list_base_get_property; @@ -1239,7 +1223,7 @@ autoscroll_cb (GtkWidget *widget, value = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_VERTICAL]); gtk_adjustment_set_value (priv->adjustment[GTK_ORIENTATION_VERTICAL], value + priv->autoscroll_delta_y); - if (priv->doing_rubberband) + if (priv->rubberband) { priv->rb_x2 += priv->autoscroll_delta_x; priv->rb_y2 += priv->autoscroll_delta_y; @@ -1277,6 +1261,32 @@ remove_autoscroll (GtkListBase *self) } } +void +gtk_list_base_allocate_rubberband (GtkListBase *self) +{ + GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); + GdkRectangle rect; + double x, y; + int min, nat; + + if (!priv->rubberband) + return; + + gtk_widget_measure (priv->rubberband, + GTK_ORIENTATION_HORIZONTAL, -1, + &min, &nat, NULL, NULL); + + x = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); + y = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_VERTICAL]); + + rect.x = MIN (priv->rb_x1, priv->rb_x2) - x; + rect.y = MIN (priv->rb_y1, priv->rb_y2) - y; + rect.width = ABS (priv->rb_x1 - priv->rb_x2) + 1; + rect.height = ABS (priv->rb_y1 - priv->rb_y2) + 1; + + gtk_widget_size_allocate (priv->rubberband, &rect, -1); +} + static void gtk_list_base_start_rubberband (GtkListBase *self, double x, @@ -1285,11 +1295,10 @@ gtk_list_base_start_rubberband (GtkListBase *self, gboolean extend) { GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); - GtkCssNode *widget_node; double value_x, value_y; GtkSelectionModel *selection; - if (priv->doing_rubberband) + if (priv->rubberband) return; value_x = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); @@ -1301,20 +1310,14 @@ gtk_list_base_start_rubberband (GtkListBase *self, priv->modify = modify; priv->extend = extend; - widget_node = gtk_widget_get_css_node (GTK_WIDGET (self)); - priv->rubberband_node = gtk_css_node_new (); - gtk_css_node_set_name (priv->rubberband_node, - g_quark_from_static_string ("rubberband")); - gtk_css_node_set_parent (priv->rubberband_node, widget_node); - gtk_css_node_set_state (priv->rubberband_node, gtk_css_node_get_state (widget_node)); - g_object_unref (priv->rubberband_node); + priv->rubberband = gtk_gizmo_new ("rubberband", + NULL, NULL, NULL, NULL, NULL, NULL); + gtk_widget_set_parent (priv->rubberband, GTK_WIDGET (self)); selection = gtk_list_item_manager_get_model (priv->item_manager); if (modify) priv->old_selection = GTK_SELECTION_MODEL (gtk_multi_selection_copy (selection)); - - priv->doing_rubberband = TRUE; } static void @@ -1322,13 +1325,10 @@ gtk_list_base_stop_rubberband (GtkListBase *self) { GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); - if (!priv->doing_rubberband) + if (!priv->rubberband) return; - priv->doing_rubberband = FALSE; - gtk_css_node_set_parent (priv->rubberband_node, NULL); - priv->rubberband_node = NULL; - + g_clear_pointer (&priv->rubberband, gtk_widget_unparent); g_clear_object (&priv->old_selection); remove_autoscroll (self); @@ -1347,7 +1347,7 @@ gtk_list_base_update_rubberband (GtkListBase *self, double value_x, value_y, page_size, upper; double delta_x, delta_y; - if (!priv->doing_rubberband) + if (!priv->rubberband) return; value_x = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); @@ -1392,17 +1392,11 @@ gtk_list_base_update_rubberband_selection (GtkListBase *self) GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); GdkRectangle rect; GdkRectangle alloc; - double value_x, value_y; GtkSelectionModel *model; GtkListItemManagerItem *item; - value_x = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); - value_y = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_VERTICAL]); - - rect.x = MIN (priv->rb_x1, priv->rb_x2) - value_x; - rect.y = MIN (priv->rb_y1, priv->rb_y2) - value_y; - rect.width = ABS (priv->rb_x1 - priv->rb_x2) + 1; - rect.height = ABS (priv->rb_y1 - priv->rb_y2) + 1; + gtk_list_base_allocate_rubberband (self); + gtk_widget_get_allocation (priv->rubberband, &rect); model = gtk_list_item_manager_get_model (priv->item_manager); @@ -1435,37 +1429,6 @@ gtk_list_base_update_rubberband_selection (GtkListBase *self) } } -static void -gtk_list_base_snapshot_rubberband (GtkListBase *self, - GtkSnapshot *snapshot) -{ - GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); - GtkStyleContext *context; - GdkRectangle rect; - double value_x, value_y; - - if (!priv->doing_rubberband) - return; - - value_x = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); - value_y = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_VERTICAL]); - - rect.x = MIN (priv->rb_x1, priv->rb_x2) - value_x; - rect.y = MIN (priv->rb_y1, priv->rb_y2) - value_y; - rect.width = ABS (priv->rb_x1 - priv->rb_x2) + 1; - rect.height = ABS (priv->rb_y1 - priv->rb_y2) + 1; - - context = gtk_widget_get_style_context (GTK_WIDGET (self)); - - gtk_style_context_save_to_node (context, priv->rubberband_node); - - gtk_snapshot_render_background (snapshot, context, rect.x, rect.y, rect.width, rect.height); - gtk_snapshot_render_frame (snapshot, context, rect.x, rect.y, rect.width, rect.height); - - gtk_style_context_restore (context); - -} - static void get_selection_modifiers (GtkGesture *gesture, gboolean *modify, diff --git a/gtk/gtklistbaseprivate.h b/gtk/gtklistbaseprivate.h index 73d20151c8..7cf0504a43 100644 --- a/gtk/gtklistbaseprivate.h +++ b/gtk/gtklistbaseprivate.h @@ -103,4 +103,6 @@ void gtk_list_base_set_enable_rubberband (GtkListBase gboolean enable); gboolean gtk_list_base_get_enable_rubberband (GtkListBase *self); +void gtk_list_base_allocate_rubberband (GtkListBase *self); + #endif /* __GTK_LIST_BASE_PRIVATE_H__ */ diff --git a/gtk/gtklistview.c b/gtk/gtklistview.c index 30cd6bc847..811636e6e0 100644 --- a/gtk/gtklistview.c +++ b/gtk/gtklistview.c @@ -516,6 +516,8 @@ gtk_list_view_size_allocate (GtkWidget *widget, GtkOrientation orientation, opposite_orientation; GtkScrollablePolicy scroll_policy; + gtk_list_base_allocate_rubberband (GTK_LIST_BASE (self)); + orientation = gtk_list_base_get_orientation (GTK_LIST_BASE (self)); opposite_orientation = OPPOSITE_ORIENTATION (orientation); scroll_policy = gtk_list_base_get_scroll_policy (GTK_LIST_BASE (self), orientation); -- 2.30.2